package ygflower.dao.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceException;

import org.springframework.orm.jpa.JpaCallback;
import org.springframework.orm.jpa.support.JpaDaoSupport;
import org.springframework.transaction.annotation.Transactional;

import ygflower.dao.GenericDao;



@SuppressWarnings("unchecked")
@Transactional
public class GenericDaoImpl<T, ID extends Serializable> extends JpaDaoSupport
		implements GenericDao<T, ID> {

	private Class persistentClass;
	public String ClassName;

	public GenericDaoImpl() {
		this.persistentClass = (Class) ((ParameterizedType) getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0];
		this.ClassName = persistentClass.getSimpleName();
	}

	public Class getPersistentClass() {
		return persistentClass;
	}

	public T save(Object entity) {
		getJpaTemplate().persist(entity);
		return (T)entity;
	}

	public T update(Object entity) {
		getJpaTemplate().merge(entity);
		return (T)entity;
	}

	public Integer updateBySql(final String sql){
		return (Integer)getJpaTemplate().execute(new JpaCallback(){
			public Integer doInJpa(EntityManager em) throws PersistenceException{
				return em.createNativeQuery(sql).executeUpdate();
			}
		});
	}

	public void delete(Object entity) {
		getJpaTemplate().remove(entity);
	}
	
	public T findById(Serializable id) {
		return (T)getJpaTemplate().find(this.getPersistentClass(), id);
	}
	public List find(String name,String value){
		Map<String, String> params = new HashMap<String, String>();
        params.put(name, value);
        String sql = "from " + ClassName + " as t where t." + name +" = :"+name;
		StringBuffer jpql = new StringBuffer("from ");
		jpql.append(getPersistentClass().getName());
		jpql.append(" as t where t.");
		jpql.append(name); 
		jpql.append("=:");
		jpql.append(name);
		return getJpaTemplate().findByNamedParams(jpql.toString(), params);
//		return getJpaTemplate().executeFind(new JpaCallback() {
//			public Object doInJpa(EntityManager em) throws PersistenceException {
//				StringBuffer jpql = new StringBuffer("from ");
//				jpql.append(getPersistentClass().getName());
//				jpql.append(" as t where t.");
//				jpql.append(getPersistentClass().getName());
//				
//				return em.createQuery(jpql.toString()).getResultList();
//			}
//		});        
	}
	public List findByJPQL(String jpql) {
		return getJpaTemplate().find(jpql);
	}

	/**
	 * 返回：list中装入的是对象数组(Object[])
	 */
	public List findBySQL(final String sql) {
		return  getJpaTemplate().executeFind(new JpaCallback(){
			public List doInJpa(EntityManager em) throws PersistenceException{
				return em.createNativeQuery(sql).getResultList();
			}
		});
	}

	public List findAll() {
		return getJpaTemplate().executeFind(new JpaCallback() {
			public Object doInJpa(EntityManager em) throws PersistenceException {
				StringBuffer jpql = new StringBuffer("from ");
				jpql.append(getPersistentClass().getName());
				jpql.append(" obj");
				return em.createQuery(jpql.toString()).getResultList();
			}
		});
	}

	
	public int findRowCount() {
		return ((Long) getJpaTemplate().execute(new JpaCallback() {
			public Object doInJpa(EntityManager em) throws PersistenceException {
				StringBuffer strBuff = new StringBuffer("select count(*) from ");
				strBuff.append(getPersistentClass().getName());
				return em.createQuery(strBuff.toString()).getResultList().get(0);
			}
		})).intValue();
	}
	
}
